iT邦幫忙

2023 iThome 鐵人賽

DAY 7
0
自我挑戰組

【菜鳥冒險記】用React與Firebase開始sideproject之路系列 第 7

[Day7]將Firebase加到App中:TODO List(三)

  • 分享至 

  • xImage
  •  

前置動作

Firebase在coding實作的概念,與其他module一樣,必須先安裝好模組。

第一步,想來看到這裡都已經得心應手,要跑command line npm install firebase,這時候可能遇到npm版本問題,導致報錯, ̶我̶一̶律̶建̶議̶加̶上̶f̶o̶r̶c̶e̶。

接著,打開我們在第三天建立過的firebase.js,從firebase裡面存取你的App下來,以便後續使用collection。

// firebase.js
import { initializeApp } from 'firebase/app';

const firebaseConfig = {
    apiKey: {your key},
    authDomain: {your auth},
    projectId: {your Id},
    storageBucket: {yours},
    messagingSenderId: {your Id},
    appId: {yours}
};

const firebaseApp = initializeApp(firebaseConfig)

export default firebaseApp;

建立cloud firestore

回到firebase的主頁,我們可以開始建立一個實際的雲端資料庫了。

https://ithelp.ithome.com.tw/upload/images/20230922/20163080dQaThh3e6a.png
從你的專案頁點入,會看到Cloud Firestore的選項,點選建立。之後在設定頁選擇Start in test mode

https://ithelp.ithome.com.tw/upload/images/20230922/20163080J06Cp7RPy1.png
完成初步設定,就可以start collection了!

https://ithelp.ithome.com.tw/upload/images/20230922/20163080VZETSuqLbp.png
為你的collection取一個ID,這一步很重要,要記得自己取的ID,因為在project中要存取你所往上送的資料,需要透過ID來找到這個collection。

https://ithelp.ithome.com.tw/upload/images/20230922/20163080ByGJa50xna.png
繼續完成初始設定,這邊的Document ID很貼心地提供了一個隨機的選項。按下確認後,就完成Cloud Firestore的建立了。

程式碼概念

這次引入firebase,就是在做資料的存取,我們第一時間可以反應到,它會更改到的是與todos有關的部分。

首先,要瞭解到資料庫內部存取資料,以及原先使用的const差異。我們在螢幕上看到任何資料的變化,都是const的變化,因為在React 中,狀態可以分為局部狀態和全域狀態。局部狀態是指只在單一component內部使用的狀態(即使App.js,也視為單一的component),通常使用useState來管理。全域狀態是在多個components之間共享的狀態,通常需要使用Redux或React 的 Context API來實作。

在執行全域性變化時,可以使用useEffect來監控操作。

useEffect 是 React 提供的一個鉤子函數,用於處理交互操作,例如資料獲取、訂閱、手動操作 DOM 等。它在function的設計中模擬了component的生命週期方法 componentDidMount、componentDidUpdate 和 componentWillUnmount。

所以在我們這次的實作中,主要要處理的就是:

  • 最開始進入網頁時,要看到存在資料庫裡的todos
    • 首先,要有一個區域性的資料庫,就像是看一本食譜,要做任何菜之前,先把食材從冰箱拿出來、放到流理台上,才會繼續備料、煎煮等。這裡需要查詢firebase的用法,collection可以派上用場
    • 利用useEffect可以監控,這裡或許與firebase的實作有關,可以利用一個map遍歷資料庫內容並存入區域的todo
  • 新的todo輸入後,要存進資料庫裡
    • 這裡需要查詢firebase的用法,我們可以思考如何從collection中拿出資訊, addDoc或getDocs這兩個function能派上用場。
  • 新的todo輸入後,要能夠在畫面上顯示
    • 即時更新到區域的todo上面。

順著這個思路,就可以完成今天的實作了。

完整code

// App.js
import { useState, useEffect } from 'react'
import { Button, FormControl, Input, InputLabel } from '@material-ui/core';
import Todo from './component/Todo'
import { getFirestore, collection, addDoc, getDocs } from "firebase/firestore";
import firebaseApp from "./firebase";

import './App.css';

function App() {
  const [todos, setTodos] = useState([])

  const db = getFirestore(firebaseApp);
  const todosCollection = collection(db, 'todos');

  const [input, setInput] = useState('');

  useEffect(() => {
    const fetchTodos = async () => {
      const querySnapshot = await getDocs(todosCollection);
      const todosData = querySnapshot.docs.map((doc) => doc.data().todo);
      setTodos(todosData);
    };

    fetchTodos();
  }, []);

  const addTodo = async (input) => {
    console.log("enter")
    try {
      // const todosCollection = collection(db, "todos");
      await addDoc(todosCollection, {
        todo: input,
      });
      console.log("Todo added successfully!");
      setTodos([...todos, input])
      setInput('')
    } catch (error) {
      console.error("Error adding todo: ", error);
    }
  }

  return (
    <div className="App">
      <h1>My TODO List</h1>
      <form onSubmit={(e) => { e.preventDefault(); addTodo(input); }}>
        <FormControl>
          <InputLabel>Write a TODO</InputLabel>
          <Input value={input} onChange={e => setInput(e.target.value)} />
        </FormControl>
        <Button type="submit" onClick={addTodo} variant='contained' color="primary" disabled={!input}>Add TODO</Button>
      </form>
      <ul>
        {todos.map(it => <Todo todo={it} />)}
      </ul>
    </div>
  );
}

export default App;

https://ithelp.ithome.com.tw/upload/images/20230922/20163080NEPSFzrE6K.png
最後,你可以得到一個像這樣的網頁。


上一篇
[Day6]用material UI改善介面:TODO List(二)
下一篇
[Day8]考慮需求、增加功能:TODO List(三)
系列文
【菜鳥冒險記】用React與Firebase開始sideproject之路20
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言